Step by Step: How to build your first JavaFX application
= Motivation / Goal = Just looking at JavaFX code doesn't get you too far in terms of understanding it. Let's create a little problem for us to solve in JavaFX. Going through the steps one-by-one is really the only way to learn. Something simple. How about a calculator? A text field, some buttons with actions, we're all good. Oh, wait, I'm way to lazy for that. Let's scale it back to something like a calculator. How about, a frame with a text field, which is not editble. There will be buttons to add characters to the text field, or clear it out. Upon every textfield change, let's print the old and new text value. Pretty simple, pretty useless. But it should hit upon several JavaFX features. Afterwards, we will make an equivalent swing version. = Building the JavaFX application = Let's make an attempt at the JavaFX version. You will want to at least follow the https://openjfx.dev.java.net/Getting_Started_With_JavaFX.html Getting Started tutorial over on OpenJFX to the point of getting your IDE set up. Eclipse set-up is largely the same as Netbeans, so the instructions there still apply. Hello World We'll start with the Hello World example on that page: Adding a text field So, there are a good amount of changes needed to reach our goal. We'll need a textfield, one that is not editible: Notice that I swapped out the label component, and just kept on defining properties no matter how far in we are, like editable on textfield. Multiple Components We need to add buttons, so we will have multiple components in this frame. Traditional GUI programming would have us set up layout managers to accomplish this. For this simplistic example, we can get by with a simplistic layout: FlowLayout. In JavaFX, there are some convenience classes that help us with this: xxPanels. For a FlowLayout, we have a FlowPanel. We simply use an array of components, denoted by the 'and '' symbols. Each component is seperated by commas, as in Java. Note that, also like Java, the final component can have a trailing comma, which is ignored (see tag note2). A frame's content also allows an array of components, but this doesn't work the same way. Comment out the two lines tagged note1 to see what it does. This is actually just like what would happen in a Swing application when multiple components are added. They are all added to the Frame's BorderLayout.CENTER, overlaying each other. Adding Behavior We want something to happen in response to button clicks, namely that they change the value of the textfield. To get to that point, we need to add the equivalent of ActionListeners to our buttons. From this point on, the preview of the GUI stays the same, so I will not be including them. Also, you must have the Java Console visible, or be running JavaFX from the command line in order to see the System.out.println results. Adding an ActionListener is pretty straightforward. Define an operation() that does what you want. However, what we want is to change the text in the textfield, and we can't quite get there just yet. Also note the import statement tagged with note1... almost every class must be imported explicitly. There is no freebie import java.lang.* as there is when coding Java. Binding a data model to a view In JavaFX, a developer is free to define new classes and assign them to variables, just as we have been doing for the frames we have been creating in the above examples ("var frame = Frame..." This provides great flexibility in how we organize our code, and can help in separating out non-visual behavior and clarifying the code. There is something else, something very cool, that building our own data models provides us: binding. We can make the value of some attributes dependent on others. For example, we can make the textField's text attribute dependent upon some other value, one that is easier for our buttons to access. There are three new entries at the top of the file: A class definition, a method definition, and a variable declaration. The class definition defines the values present on an object (attributes) and the methods (operations). The first strange thing you'll notice (lines tagged note1) is that the operation is not actually defined within the class definition. This was an intentional feature... see some of Chris Oliver's early postings to the mailing lists (TODO add link) as to why. The variable declaration (tagged note2) is creating a new instance of TextValue and assigning its value attribute to "Hello, Model". Our TextField's value attribute (tagged note3 is now a little different. Rather than specifiying its initial value as we declare the text field, we are telling it to use the value of model.value. Furthermore, since we are using the bind keyword, we are telling it to update every time that model.value updates. Also note that the binding is two-way; if the text field were editable, every change made to it would be reflected in model.value. At the lines tagged note4 we have made the a''' and '''b buttons change the value of the model by concatenating 'a' or 'b' to the end of the string. Note also that we don't have the convenience of using the '+' operator... it is not overloaded for string usage. For the Clear button's behavior (at note5) we could have done something similar to the other buttons, by assigning model.value = "". We used the operation clear() here just to show its use. Adding Triggers We are missing one thing from our original specification: Every time the text field changes, we want to print its contents to standard out. There is no syntax for adding a little code to the bind instruction; we can't just insert a sysout there. So, we can move on to triggers, a bind-like feature of JavaFX. It allows us to do something when an attribute changes. Triggers are more sophisticated than shown here, this is only a simple usage. The only change here is at note1. The syntax for triggers is almost insane, and could quite possibly change. The first line says what we are watching (TextValue.value), the variable name to use for the old value (oldValue) and the variable name to use for the new value (newValue). The phrase oldValue is optional and can be left off if you won't be referencing the old value. Final and Annotated version Here is the final version of the fx file, along with lots of comments inline. The Swing Version For completeness, then, let's go back and make a Java Swing version just to see what it looks like compared to the JavaFX version. I'll skip the intermediate steps and present the final Swing version here: Category:Tutorial